page.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import {serverGet, serverPost} from "@/utils/request"
  2. import {DollarSign, MapPin, Phone, Tag, User, Users} from "lucide-react"
  3. import Link from "next/link"
  4. import {Breadcrumb} from "antd";
  5. export const dynamicParams = true
  6. export async function generateStaticParams() {
  7. const res = await serverPost<Page<RecruitmentInfo>, { pageNum: number; pageSize: number }>(
  8. "webSite/getRecruitmentInfoByPage",
  9. { pageNum: 1, pageSize: 20 }
  10. )
  11. return res.data.records.map((item) => ({
  12. id: item.id,
  13. }))
  14. }
  15. export default async function RecruitmentDetailPage({
  16. params,
  17. }: {
  18. params: Promise<{ id: string }>
  19. }) {
  20. const { id } = await params
  21. const detail = await serverGet<RecruitmentInfo, { id: string }>(
  22. "webSite/getRecruitmentInfoById",
  23. { id }
  24. )
  25. if (!detail) {
  26. return (
  27. <div className="w-4/5 mx-auto py-20 text-center text-gray-500">
  28. 暂无该岗位信息
  29. </div>
  30. )
  31. }
  32. return (
  33. <>
  34. <div className="w-4/5 mx-auto">
  35. <div className="pt-10 ml-20 flex gap-2">
  36. <span className="text-sm">您当前的所在位置:</span>
  37. <Breadcrumb
  38. separator=">"
  39. items={[
  40. {title: "关于我们", href: "/about"},
  41. {title: "招聘列表", href: "/about/recruitList"},
  42. {title: detail.data.jobOpenings},
  43. ]}
  44. />
  45. </div>
  46. </div>
  47. <div className="w-11/12 lg:w-4/5 mx-auto py-12">
  48. {/* 卡片 */}
  49. <div className="bg-white shadow-2xl rounded-2xl p-6 sm:p-10 relative overflow-hidden">
  50. {/* 蓝色渐变背景 */}
  51. <div
  52. className="absolute inset-0 bg-gradient-to-r from-blue-100 via-blue-200 to-blue-300 opacity-50 rounded-2xl -z-10"></div>
  53. {/* 标题 */}
  54. <h1
  55. className="text-2xl sm:text-4xl font-extrabold mb-8 bg-gradient-to-r from-blue-600 to-blue-800 bg-clip-text text-transparent">
  56. {detail.data.jobOpenings}
  57. </h1>
  58. {/* 信息列表 */}
  59. <div className="grid gap-5 sm:grid-cols-2">
  60. <InfoItem icon={<MapPin className="w-5 h-5 text-blue-600"/>} label="工作地址"
  61. value={detail.data.workLocation}/>
  62. <InfoItem icon={<Users className="w-5 h-5 text-blue-600"/>} label="招聘人数"
  63. value={detail.data.numberRecruits}/>
  64. <InfoItem icon={<DollarSign className="w-5 h-5 text-blue-600"/>} label="薪资" value={detail.data.salary}/>
  65. <InfoItem icon={<User className="w-5 h-5 text-blue-600"/>} label="联系人" value={detail.data.contact}/>
  66. <InfoItem icon={<Phone className="w-5 h-5 text-blue-600"/>} label="联系方式"
  67. value={detail.data.contactInformation}/>
  68. {detail.data.keyTerms && (
  69. <InfoItem icon={<Tag className="w-5 h-5 text-blue-600"/>} label="关键词" value={detail.data.keyTerms}/>
  70. )}
  71. </div>
  72. {/* 岗位描述 */}
  73. <div className="mt-10">
  74. <h2 className="text-xl sm:text-2xl font-semibold mb-4 text-gray-800">岗位要求</h2>
  75. <p className="leading-relaxed text-gray-700 text-sm sm:text-base">{detail.data.jobRequirements}</p>
  76. </div>
  77. {/* 备注:独立框,空时不渲染 */}
  78. {detail.data.remarks?.trim() && (
  79. <div
  80. className="mt-8 bg-blue-50 border border-blue-200 rounded-xl p-4 sm:p-6 min-h-[100px] flex items-center">
  81. <p className="text-gray-700 text-sm sm:text-base">{detail.data.remarks}</p>
  82. </div>
  83. )}
  84. {/* 返回按钮 */}
  85. <div className="mt-10 text-center">
  86. <Link
  87. href="/about/recruitList"
  88. className="inline-block px-6 py-3 bg-gradient-to-r from-blue-500 to-blue-700 text-white rounded-full shadow-lg hover:scale-105 transition-transform text-sm sm:text-base"
  89. >
  90. 返回招聘列表
  91. </Link>
  92. </div>
  93. </div>
  94. </div>
  95. </>
  96. )
  97. }
  98. // 信息展示子组件
  99. function InfoItem({icon, label, value}: { icon: React.ReactNode; label: string; value: any }) {
  100. return (
  101. <div className="flex items-center space-x-3 bg-gray-50 rounded-xl p-3 sm:p-4 shadow-sm hover:shadow-md transition">
  102. {icon}
  103. <div>
  104. <p className="text-xs sm:text-sm text-gray-500">{label}</p>
  105. <p className="text-sm sm:text-base font-medium text-gray-800 break-words">{value}</p>
  106. </div>
  107. </div>
  108. )
  109. }